package com.lyw.utils;

import com.lyw.constants.GlobalVariables;
import com.lyw.domain.GlobalConfigurationInfo;
import com.lyw.enums.CharacterEnum;
import com.lyw.enums.DuplicateEnum;
import com.lyw.factory.TimerTaskFactory;
import com.lyw.handle.DataFilteringAdapter;
import org.opencv.core.Mat;

import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.lyw.constants.CommonConstants.*;

public class DuplicateUtil {

  private DuplicateUtil() {
  }

  /**
   * 开始刷副本
   */
  public static void openDungeon(TimerTaskFactory taskFactory, Robot robot, Rectangle rectangle, GlobalConfigurationInfo configInfo, DuplicateEnum duplicateInfo) throws Exception {
    taskFactory.execute(() -> {
      while (true) {
        OpenCvUtil.dynamicCharacterPosition(robot, 90);
      }
    });
    robot.delay(100);
    // 确定人物在地图中的坐标位置
    int[] cur_characters_position_on_the_mini_map = SmallMapUtil.getTheMiniMapWhereTheCharacterIsLocated(robot, duplicateInfo);
    GlobalVariables.setMini_map_position(cur_characters_position_on_the_mini_map);

    // 下一个房间坐标位置
    int[] nextRoomPosition = duplicateInfo.getNextRoomPosition(cur_characters_position_on_the_mini_map);
    GlobalVariables.setNext_room_position(nextRoomPosition);
    int[] endRoomPositions = duplicateInfo.getEndRoomPosition();
    int[] startRoomPositions = duplicateInfo.getStartRoomPosition();
    int height = configInfo.getCurCharacter().getRoleWidthHeight()[1];

    while (true) {
      if (cur_characters_position_on_the_mini_map[0] == startRoomPositions[0] && cur_characters_position_on_the_mini_map[1] == startRoomPositions[1]) {
        FileUtils.clearClearancePosition();
      }
      cur_characters_position_on_the_mini_map = GlobalVariables.getMini_map_position();
      nextRoomPosition = duplicateInfo.getNextRoomPosition(GlobalVariables.getMini_map_position());
      GlobalVariables.setNext_room_position(nextRoomPosition);

      FileUtils.writeClearanceRoomPosition(cur_characters_position_on_the_mini_map);
      // 开打
      fightingMonsters(taskFactory, robot, rectangle, configInfo.getCurCharacter(), duplicateInfo, height);

      cur_characters_position_on_the_mini_map = SmallMapUtil.getTheMiniMapWhereTheCharacterIsLocated(robot, duplicateInfo);

      if (cur_characters_position_on_the_mini_map[0] == endRoomPositions[0] && cur_characters_position_on_the_mini_map[1] == endRoomPositions[1]) {
        TimeUnit.SECONDS.sleep(3);
        MouseAndKeyEventUtil.keyEnter(KeyEvent.VK_NUMPAD1);
        for (int i = 0; i < 10; i++) {
          TimeUnit.MILLISECONDS.sleep(500);
          MouseAndKeyEventUtil.keyEnter(KeyEvent.VK_X);
        }
        return;
      }

      moveRoleToDoor(robot, rectangle, configInfo.getCurCharacter(), duplicateInfo);
      // 捡装备，去下一个房间
    }
  }

  public static void moveRoleToDoor(Robot robot,
                                    Rectangle rectangle,
                                    CharacterEnum character,
                                    DuplicateEnum duplicateInfo) throws Exception {

    int height = character.getRoleWidthHeight()[1];
    int[] positions = {GlobalVariables.POSITIONS[0], GlobalVariables.POSITIONS[1]};
    DataFilteringAdapter positionAdapter = SmallMapUtil.getNextRoom(duplicateInfo);
//    DataFilteringAdapter positionAdapter = new TopProcessor();
    DataFilteringAdapter.prepareMove(rectangle, positions, height);
    positionAdapter.mobileCharacterToDoor(robot, rectangle, duplicateInfo);
  }

  public static void moveRoleToDoor1(TimerTaskFactory taskFactory,
                                    Robot robot,
                                    Rectangle rectangle,
                                    CharacterEnum character,
                                    DuplicateEnum duplicateInfo) throws Exception {

    int height = character.getRoleWidthHeight()[1];
    int[] keycode = {-1}, counts = {0, 0}, pro = {-1, -1, rectangle.x, rectangle.y},
            positions = {-1, -1, -1, -1},
            startPosition = {(int) rectangle.getX(), (int) rectangle.getY()};

    DataFilteringAdapter filter = SmallMapUtil.getNextRoom(duplicateInfo);
    int[] cur_characters_position_on_the_mini_map = GlobalVariables.getMini_map_position();

    int[] characters = OpenCvUtil.getCharacter(robot, rectangle, height);
    positions[0] = characters[0];
    positions[1] = characters[1];
    // 移动到不能动的位置
    DataFilteringAdapter.prepareMove(rectangle, positions, height);
    DataFilteringAdapter.move(filter);
    while (true) {
      characters = OpenCvUtil.getCharacter(robot, rectangle, height);
      if (!CharacterUtil.confirmWhetherMove(counts, pro, characters)) {
        System.out.println("移动到了下一个房间门 [ " + filter.position_name + " ] 旁边！");
        break;
      }
      int[] cur_character_position_on_the_mini_map = SmallMapUtil.getTheMiniMapWhereTheCharacterIsLocated(robot, duplicateInfo);
      int[] boss_position = OpenCvUtil.getBossPosition(SmallMapUtil.getBossPosition(robot), duplicateInfo.getMapSize());
      if ((cur_character_position_on_the_mini_map[0] != -1 || boss_position[0] != -1) &&
              (cur_character_position_on_the_mini_map[0] != cur_characters_position_on_the_mini_map[0]
              ||
              cur_character_position_on_the_mini_map[1] != cur_characters_position_on_the_mini_map[1])
      ) {
        System.out.println("success move!");
        DataFilteringAdapter.released(filter);
//        MouseAndKeyEventUtil.keyReleased(keycode[0]);
        if (cur_character_position_on_the_mini_map[0] != -1) {
          GlobalVariables.setMini_map_position(cur_character_position_on_the_mini_map);
        } else if (boss_position[0] != -1){
          GlobalVariables.setMini_map_position(boss_position);
        }
        return;
      }
    }

    while (true) {
      OpenCvUtil.getRoleAndDoorPosition(robot, filter, robot.createScreenCapture(rectangle), startPosition, taskFactory, height, positions);

      if (positions[2] != -1) { // 找到门了
        System.out.println("confirm correct");
        // 确认是否是正确门口
        if (filter.confirmIfTheDoorIsCorrect(positions)) {
          break;
        }
      }
      if (!CharacterUtil.confirmWhetherMove(counts, pro, positions)) {
        System.out.println("no move");
        // 只可能障碍物
        filter.mobileFindDoor(counts, keycode);
      }
      counts[0]++;
      System.out.println("find door");
      int[] cur_character_position_on_the_mini_map = SmallMapUtil.getTheMiniMapWhereTheCharacterIsLocated(robot, duplicateInfo);
      int[] boss_position = OpenCvUtil.getBossPosition(SmallMapUtil.getBossPosition(robot), duplicateInfo.getMapSize());
      if ((cur_character_position_on_the_mini_map[0] != -1 || boss_position[0] != -1) &&
              (cur_character_position_on_the_mini_map[0] != cur_characters_position_on_the_mini_map[0]
              ||
              cur_character_position_on_the_mini_map[1] != cur_characters_position_on_the_mini_map[1])
      ) {
        System.out.println("success move!");
        DataFilteringAdapter.released(filter);
        if (keycode[0] != -1) {
          MouseAndKeyEventUtil.keyReleased(keycode[0]);
        }
        if (cur_character_position_on_the_mini_map[0] != -1) {
          GlobalVariables.setMini_map_position(cur_character_position_on_the_mini_map);
        } else if (boss_position[0] != -1){
          GlobalVariables.setMini_map_position(boss_position);
        }
        return;
      }
    }
    System.out.println("move to door");
    // 移动到门口
    filter.mobileCharacterToCorrectDoor(positions, keycode);
    while (true) {

      int[] cur_character_position_on_the_mini_map = SmallMapUtil.getTheMiniMapWhereTheCharacterIsLocated(robot, duplicateInfo);
      int[] boss_position = OpenCvUtil.getBossPosition(SmallMapUtil.getBossPosition(robot), duplicateInfo.getMapSize());
      if ((cur_character_position_on_the_mini_map[0] != -1 || boss_position[0] != -1) &&
              (cur_character_position_on_the_mini_map[0] != cur_characters_position_on_the_mini_map[0]
              ||
              cur_character_position_on_the_mini_map[1] != cur_characters_position_on_the_mini_map[1])
      ) {
        System.out.println("success move!");
        DataFilteringAdapter.released(filter);
        if (keycode[0] != -1) {
          MouseAndKeyEventUtil.keyReleased(keycode[0]);
        }
        if (cur_character_position_on_the_mini_map[0] != -1) {
          GlobalVariables.setMini_map_position(cur_character_position_on_the_mini_map);
        } else if (boss_position[0] != -1){
          GlobalVariables.setMini_map_position(boss_position);
        }
        return;
      }
    }
    /*while (true) {
      int[] position1 = OpenCvUtil.getCharacter(robot, rectangle, character);
      if (position[0] == position1[0] && position[1] == position1[1]) {
        MouseAndKeyEventUtil.keyReleased(duplicateInfo.getRoute()[room].getKeyCode());
        break;
      }
      robot.delay(60);
      position = position1;
    }

    try {
      // 找门
      while (true) {
        long start = System.currentTimeMillis();
        CountDownLatch count = new CountDownLatch(2);
        Mat mat = OpenCvUtil.bufferedImageToMat(robot.createScreenCapture(rectangle));
        Mat res1 = new Mat(mat.rows(), mat.cols(), CvType.CV_32FC1);
        Mat res2 = new Mat(mat.rows(), mat.cols(), CvType.CV_32FC1);
        taskFactory.execute(() -> {
          Imgproc.matchTemplate(mat, door, res2, Imgproc.TM_CCORR);
          count.countDown();
        });

        taskFactory.execute(() -> {
          Imgproc.matchTemplate(mat, character, res1, Imgproc.TM_CCORR);
          count.countDown();
        });

        count.await();
        Core.normalize(res2, res2, 0, 1, Core.NORM_MINMAX, -1, new Mat());
        Core.normalize(res1, res1, 0, 1, Core.NORM_MINMAX, -1, new Mat());
        Core.MinMaxLocResult min1 = Core.minMaxLoc(res1);
        characterPosition[0] = (int) min1.maxLoc.x;
        characterPosition[1] = (int) min1.maxLoc.y;
        rows = res2.rows();
        cols = res2.cols();

        if (!theTargetDoor) {

          // TODO 找到精准不，然后移动是否有障碍物
          theTargetDoor = filter.findTheTargetDoor(robot, res2, rows, cols, characterPosition);
          if (!theTargetDoor) { // 没有找到，尝试寻找
            filter.mobileCharacterSearchTarget(robot, keyboard);
            continue;
          }
        }

        // 找到下一个门之后进行移动
        filter.mobileCharacterToDoor(robot, keyboard, characterPosition, filter.position);
        robot.keyRelease(keyboard[0]);
        System.out.println("door [0] -> " + (System.currentTimeMillis() - start));

        if (clearance[0]) {
          MouseAndKeyEventUtil.keyReleased(KeyEvent.VK_UP);
          clearance[0] = false;
          break;
        }
      }
    } catch (InterruptedException e) {
      e.printStackTrace();
    }*/
  }

  /**
   * 开始打怪
   */
  private static void fightingMonsters(TimerTaskFactory taskFactory,
                                       Robot robot,
                                       Rectangle rectangle,
                                       CharacterEnum character,
                                       DuplicateEnum duplicateInfo,
                                       int height) throws Exception {
    Map<String, Integer> skillContainers = new HashMap<>();

    int[] positions = {-1, -1, -1, -1},
            startPosition = {(int) rectangle.getX(), (int) rectangle.getY()}, skill_args = {-1, -1, -1};
    int i = 0, skill_code = 0;
    final boolean[] isSuccess = {false, false};
    int[] skillList = character.getSkill_list(GlobalVariables.getMini_map_position());
    System.out.println("技能列表 -> " + Arrays.toString(skillList));
    while (true) {
      // 2、窗口有怪
      // 确定技能
      int[] miniCharacter = SmallMapUtil.getTheMiniMapWhereTheCharacterIsLocated(robot, duplicateInfo);;
      int[] mini_map_position = GlobalVariables.getMini_map_position();

      if (miniCharacter[0] != mini_map_position[0] || miniCharacter[1] != mini_map_position[1]) {
        FileUtils.writeClearanceRoomPosition(miniCharacter);
        GlobalVariables.setMini_map_position(miniCharacter);
        skillList = character.getSkill_list(GlobalVariables.getMini_map_position());
      }
      
      for (; i < skillList.length; i++) {
        int[] skill_arguments = character.getSkill_arguments(skillList[i]);
        if (skill_arguments[0] == 999) { // 直接释放的技能比如 buff 技能
          TimeUnit.MILLISECONDS.sleep(400);
          MouseAndKeyEventUtil.keyEnter(skillList[i]);
          continue;
        }

        if (skill_arguments[0] == 99999) { // 组合技能，一般放在最后
          TimeUnit.MILLISECONDS.sleep(400);
          MouseAndKeyEventUtil.keyEnter(skillList[i]);
          TimeUnit.MILLISECONDS.sleep(400);
          MouseAndKeyEventUtil.keyEnter(skillList[i + 1]);
          TimeUnit.MILLISECONDS.sleep(400);
          MouseAndKeyEventUtil.keyEnter(skillList[i]);
          break;
        }

        // 普通技能
        skill_args = skill_arguments;
        skill_code = skillList[i];
        if (++i == skillList.length) {
          i = 0;
        }
        break;
      }

      // 2.1、是否通关
      if (OpenCvUtil.matchMiniMapWhetherClearance(robot)) { // 通关
        System.out.println("没有怪物了已通关！");
        if (skillContainers.get("xKey") != null) {
          MouseAndKeyEventUtil.keyReleased(skillContainers);
        }
        return;
      }

      // 1、判定是否有怪
      BufferedImage screenCapture = robot.createScreenCapture(OpenCvUtil.characterRect);
      OpenCvUtil.getRoleAndMonsterPosition(
              startPosition,
              taskFactory,
              screenCapture,
              height,
              positions);

      // 2、没有怪物
      if (positions[2] == -1) {
        findMonsters(robot, startPosition, taskFactory, positions, height);
      }

      boolean meetTheScope = mobileCharacter(isSuccess, positions, skill_args, startPosition, skillContainers);
      if (!meetTheScope) {
        try {
          mobileCharacterToMonsterNear(positions, robot, startPosition, taskFactory, skill_args, height, isSuccess, skillContainers);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }

      if (OpenCvUtil.matchMiniMapWhetherClearance(robot)) { // 通关
        System.out.println("没有怪物了已通关！");
        MouseAndKeyEventUtil.keyReleased(skillContainers);
        return;
      }

      // 3、判定技能范围
      //  - 满足则直接释放技能，不满足则需要移动
      if (positions[2] == -1) {
        TimeUnit.MILLISECONDS.sleep(60);
        MouseAndKeyEventUtil.keyReleased(skillContainers);
        continue;
      }
      // 释放技能并且将技能设置为 已使用
      SkillUtil.releasedSkill(skill_code, skill_args);

      // game over 游戏结束了
      if (GlobalVariables.getMini_map_position()[0] == duplicateInfo.getEndRoomPosition()[0]
              && GlobalVariables.getMini_map_position()[1] == duplicateInfo.getEndRoomPosition()[1]

              && OpenCvUtil.whetherClearance(OpenCvUtil.bufferedImageToMat(robot.createScreenCapture(rectangle)))) {
        return;
      }

      pickupMaterials(taskFactory, robot, rectangle, height);

      /*if (GlobalVariables.getMini_map_position()[0] == duplicateInfo.getEndRoomPosition()[0]
              && GlobalVariables.getMini_map_position()[1] == duplicateInfo.getEndRoomPosition()[1]

              && OpenCvUtil.whetherClearance(OpenCvUtil.bufferedImageToMat(robot.createScreenCapture(rectangle)))) {
        return;
      }*/
      if (OpenCvUtil.matchMiniMapWhetherClearance(robot)) { // 通关
        System.out.println("没有怪物了已通关！");
        return;
      }
    }
  }

  private static void findMonsters(Robot robot,
                                   int[] startPosition,
                                   TimerTaskFactory taskFactory,
                                   int[] positions,
                                   int height) throws Exception {

    int[] counts = {0, 0},
            codePriority = {KeyEvent.VK_UP, KeyEvent.VK_DOWN, KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT},
            pro = {-1, -1, startPosition[0], startPosition[1]};

    // 人物在左右移动时，添加一个上下切换移动效果，用于人物排除人物实际移动，窗口没有改变
    for (int keyCode : codePriority) {
      if (keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_RIGHT) {
        TimeUnit.MILLISECONDS.sleep(60);
        MouseAndKeyEventUtil.doubleClick(keyCode);
      } else {
        TimeUnit.MILLISECONDS.sleep(60);
        MouseAndKeyEventUtil.keyPress(keyCode);
      }
      while (true) {
        Mat mat = OpenCvUtil.bufferedImageToMat(robot.createScreenCapture(OpenCvUtil.characterRect));
        OpenCvUtil.matchTemplateMonsterAndRole(startPosition, taskFactory, mat, positions, height);
        if (!CharacterUtil.confirmWhetherMove(counts, pro, positions)) {
          MouseAndKeyEventUtil.keyReleased(keyCode);
          break;
        }

        if (positions[2] != -1) {
          MouseAndKeyEventUtil.keyReleased(keyCode);
          return;
        }
      }
      TimeUnit.MILLISECONDS.sleep(300);
      MouseAndKeyEventUtil.keyReleased(keyCode);
    }
    if (positions[2] == -1) {
      findMonsters(robot, startPosition, taskFactory, positions, height);
    }
  }

  // 拾取材料
  public static void pickupMaterials(TimerTaskFactory taskFactory, Robot robot, Rectangle rectangle, int height) throws Exception {
    while (true) {
      int[] position = OpenCvUtil.matchEquipmentGetSimplePosition(taskFactory, robot, rectangle, height);
      if (position[0] == -1) {
        break;
      }
      // 移动到装备旁边
      OpenCvUtil.moveToDest(robot, rectangle, position,
              () -> OpenCvUtil.matchEquipmentGetSimplePosition(taskFactory, robot, rectangle, height),
              height);
      TimeUnit.SECONDS.sleep(2);
      MouseAndKeyEventUtil.keyPress(KeyEvent.VK_RIGHT);
      TimeUnit.MILLISECONDS.sleep(300);
      MouseAndKeyEventUtil.keyReleased(KeyEvent.VK_RIGHT);

      position = OpenCvUtil.matchEquipmentGetSimplePosition(taskFactory, robot, rectangle, height);
      if (position[0] == -1) {
        return;
      }
    }
  }

  private static boolean verification(TimerTaskFactory taskFactory, Mat mat, int height) {
    int[] positions = OpenCvUtil.matchEquipmentGetSimplePosition(taskFactory, mat, height);
    if (positions[2] != -1) {
      return true;
    }
    return false;
  }

  private static void findEquipment(Robot robot, Rectangle rectangle, List<int[]> equipments) throws Exception {
    int[] counts = {0, 0},
            codePriority = {KeyEvent.VK_DOWN, KeyEvent.VK_RIGHT, KeyEvent.VK_LEFT},
            pro = {-1, -1},positions = {-1, -1};
    int length, i = 0, keyCode;
    // 人物在左右移动时，添加一个上下切换移动效果，用于人物排除人物实际移动，窗口没有改变
    while (true) {
      equipments = OpenCvUtil.matchEquipment(OpenCvUtil.bufferedImageToMat(robot.createScreenCapture(rectangle)));
      length = equipments.size();
      if (length > 0) {
        return;
      }
      keyCode = codePriority[i];
      if (keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_RIGHT) {
        TimeUnit.MILLISECONDS.sleep(60);
        MouseAndKeyEventUtil.doubleClick(keyCode);
      } else {
        TimeUnit.MILLISECONDS.sleep(60);
        MouseAndKeyEventUtil.keyPress(keyCode);
      }

      while (true) {
        Mat mat = OpenCvUtil.bufferedImageToMat(robot.createScreenCapture(OpenCvUtil.characterRect));
        equipments = OpenCvUtil.matchEquipment(mat);
        if (!CharacterUtil.confirmWhetherMove(counts, pro, positions)) {
          TimeUnit.MILLISECONDS.sleep(100);
          MouseAndKeyEventUtil.keyReleased(keyCode);
          break;
        }

        if (equipments.size() != 0) {
          TimeUnit.MILLISECONDS.sleep(100);
          MouseAndKeyEventUtil.keyReleased(keyCode);
          return;
        }
      }

      if (++i == codePriority.length) {
        i = 0;
      }
    }
  }

  private static void mobileCharacterToMonsterNear(int[] positions,
                                                   Robot robot,
                                                   int[] startPosition,
                                                   TimerTaskFactory taskFactory,
                                                   int[] skill_release_arguments,
                                                   int height,
                                                   boolean[] isSuccess,
                                                   Map<String, Integer> skillContainers) throws Exception {
    int exceptionX = 0, exceptionY = 0,
            distanceToMonsterXLocation = 0,
            distanceToMonsterYLocation = 0,
            proX, proY,
            count = 0;


    // 检测是否成功移动怪物指定位置
    while (true) {

      // 记录上次人物坐标
      proX = positions[0];
      proY = positions[1];

      // 2.1、是否通关
      if (OpenCvUtil.matchMiniMapWhetherClearance(robot)) { // 通关
        System.out.println("移动到怪物附近已经打完！");
        return;
      }

      // 441
      // 匹配人物和怪物位置
      Mat mat = OpenCvUtil.bufferedImageToMat(robot.createScreenCapture(OpenCvUtil.characterRect));
      OpenCvUtil.matchTemplateMonsterAndRole(startPosition, taskFactory, mat, positions, height);

      // 页面没有怪物
      if (positions[2] == -1) {
        System.out.println("？？？？？？？？？？？");
        return;
      }

      int xAbs = Math.abs(positions[0] - (positions[2] + skill_release_arguments[0]));
      int yAbs = Math.abs(positions[1] - positions[3]);

      // 确定人物x轴需要的方向
      Integer xKey = skillContainers.get("xKey");
      Integer yKey = skillContainers.get("yKey");
      Integer xStatus = skillContainers.get("xStatus");
      Integer yStatus = skillContainers.get("yStatus");

//      System.out.println(positions[0] + " - " + positions[1] + " | " + (positions[2] + skill_release_arguments[0]) + " - " + positions[3]);
      // 找到了x或y，需要释放
      if (!isSuccess[0]) {
        int vkRight = KeyEvent.VK_RIGHT;
        int vkLeft = KeyEvent.VK_LEFT;
        if (
                (skill_release_arguments[0] >= 0 && positions[0] >= positions[2] + skill_release_arguments[0] - (X_POSITION_THRESHOLD / 2))
                ||
                (skill_release_arguments[0] < 0 && positions[0] < positions[2] + skill_release_arguments[0] - (X_POSITION_THRESHOLD / 2))
              &&
                (xAbs <= X_POSITION_THRESHOLD * 1.5
                ||
                positions[2] >= startPosition[0] + 800 - skill_release_arguments[0] - X_POSITION_THRESHOLD)) {
          TimeUnit.MILLISECONDS.sleep(60);
          MouseAndKeyEventUtil.keyReleased(xKey);
          skillContainers.put("xStatus", RELEASED);
          isSuccess[0] = true;
          System.out.println("released keys[0]");
        } else if (positions[0] >= positions[2] + skill_release_arguments[0] && (xKey != vkLeft || xStatus == RELEASED)) {
          TimeUnit.MILLISECONDS.sleep(60);
          MouseAndKeyEventUtil.keyReleased(xKey);
          TimeUnit.MILLISECONDS.sleep(60);
          MouseAndKeyEventUtil.keyPress(vkLeft);
          skillContainers.put("xKey", vkLeft);
          skillContainers.put("xStatus", PRESS);
          System.out.println("x 1 position error, click LEFT !");
          isSuccess[0] = false;
          continue;
        } else if (positions[0] < positions[2] + skill_release_arguments[0] && (xKey != vkRight || xStatus == RELEASED)) {
          TimeUnit.MILLISECONDS.sleep(60);
          MouseAndKeyEventUtil.keyReleased(xKey);
          TimeUnit.MILLISECONDS.sleep(60);
          MouseAndKeyEventUtil.keyPress(vkRight);
          skillContainers.put("xKey", vkRight);
          skillContainers.put("xStatus", PRESS);
          System.out.println("x 2 position error, click RIGHT !");
          isSuccess[0] = false;
          continue;
        }
      }

      if (!isSuccess[1]) {
        int vkDown = KeyEvent.VK_DOWN;
        int vkUp = KeyEvent.VK_UP;
        if (yAbs < POSITION_THRESHOLD * 1.5) {
          TimeUnit.MILLISECONDS.sleep(60);
          MouseAndKeyEventUtil.keyReleased(yKey);
          skillContainers.put("yStatus", RELEASED);
          System.out.println("released keys[1]");
          isSuccess[1] = true;
        } else if (positions[1] <= positions[3] && (yKey != vkDown || yStatus == RELEASED)) {
          TimeUnit.MILLISECONDS.sleep(60);
          MouseAndKeyEventUtil.keyReleased(yKey);
          TimeUnit.MILLISECONDS.sleep(60);
          MouseAndKeyEventUtil.keyPress(vkDown);
          skillContainers.put("yKey", vkDown);
          skillContainers.put("yStatus", PRESS);
          System.out.println("y 1 position error, click DOWN !");
          isSuccess[1] = false;
          continue;
        } else if (positions[1] > positions[3] && (yKey != vkUp || yStatus == RELEASED)) {
          TimeUnit.MILLISECONDS.sleep(60);
          MouseAndKeyEventUtil.keyReleased(yKey);
          TimeUnit.MILLISECONDS.sleep(60);
          MouseAndKeyEventUtil.keyPress(vkUp);
          skillContainers.put("yKey", vkUp);
          skillContainers.put("yStatus", PRESS);
          System.out.println("y 2 position error, click UP !");
          isSuccess[1] = false;
          continue;
        }
      }

      // 人物已经没有移动了没有移动
      if (exceptionX == positions[0] && positions[1] == exceptionY) {
        if (distanceToMonsterXLocation != xAbs && distanceToMonsterYLocation != yAbs) { // 人物固定的地方移动
          distanceToMonsterXLocation = 0;
          distanceToMonsterYLocation = 0;
          exceptionX = 0;
          exceptionY = 0;
          count = 0;
          continue;
        }
        if (count++ >= 5) {
          count = 0;
          TimeUnit.MILLISECONDS.sleep(60);
          MouseAndKeyEventUtil.keyReleased(skillContainers);
          System.out.println("character no move !!!!!!!!!!!!!!!!!");
          boolean b11 = mobileCharacter(isSuccess, positions, skill_release_arguments, startPosition, skillContainers);
          if (b11) {
            return;
          }
        }
        continue;
      }

      // 和上次坐标相同
      if (proX == positions[0] && proY == positions[1]) {
        distanceToMonsterXLocation = xAbs;
        distanceToMonsterYLocation = yAbs;
        exceptionX = proX;
        exceptionY = proY;
        ++count;
        continue;
      } else {
        exceptionX = 0;
        exceptionY = 0;
        count = 0;
      }

      if (isSuccess[0] && isSuccess[1]) {
        TimeUnit.MILLISECONDS.sleep(60);
        MouseAndKeyEventUtil.keyReleased(skillContainers);
        System.out.println("arrive next to the monster！！！！！！！");
        break;
      }
    }
  }

  private static void findNow(boolean[] isSuccess, Map<String, Integer> skillContainers) throws Exception {
    Integer whetherPress = skillContainers.get("findStatus");
    if (whetherPress == null) { // 没有按下
      Integer enabledFind = skillContainers.get("enabledFind");
      if (enabledFind == null) {
        // 释放按键
        Integer xStatus = skillContainers.get("xStatus");
        Integer yStatus = skillContainers.get("yStatus");
        if (xStatus != null && xStatus == PRESS) {
          MouseAndKeyEventUtil.keyReleased(skillContainers.get("xKey"));
          skillContainers.put("xStatus", RELEASED);
        }
        if (yStatus != null && yStatus == PRESS) {
          MouseAndKeyEventUtil.keyReleased(skillContainers.get("yKey"));
          skillContainers.put("yStatus", RELEASED);
        }

        isSuccess[0] = false;
        isSuccess[1] = false;
        // 向下移动，找怪
        MouseAndKeyEventUtil.keyPress(KeyEvent.VK_UP);
        skillContainers.put("findMonster", KeyEvent.VK_UP);
        skillContainers.put("findStatus", PRESS);
        skillContainers.put("enabledFind", ENABLED_FIND);
        System.out.println("下去了");
      } else if (enabledFind == OTHER_FIND) {

        MouseAndKeyEventUtil.keyPress(KeyEvent.VK_DOWN);
        skillContainers.put("findMonster", KeyEvent.VK_DOWN);
        skillContainers.put("findStatus", PRESS);
        System.out.println("上去了");
      } else {
        throw new RuntimeException("上下都没找到怪物！");
      }
    }
  }

  public static boolean mobileCharacter(boolean[] isSuccess,
                                        int[] positions,
                                        int[] skill_release_distance,
                                        int[] startPosition,
                                        Map<String, Integer> skillContainers) throws Exception {

    // 确定移动按键
    if (positions[0] > positions[2] + skill_release_distance[0]) {
      skillContainers.put("xKey", KeyEvent.VK_LEFT);
      System.out.println("VK_LEFT");
    } else {
      skillContainers.put("xKey", KeyEvent.VK_RIGHT);
      System.out.println("VK_RIGHT");
    }

    if (positions[1] >= positions[3]) {
      skillContainers.put("yKey", KeyEvent.VK_UP);
      System.out.println("VK_UP");
    } else {
      skillContainers.put("yKey", KeyEvent.VK_DOWN);
      System.out.println("VK_DOWN");
    }

    enterKeyboard(isSuccess, positions, skillContainers, skill_release_distance, startPosition);

    // 满足技能范围
    if (isSuccess[0] && isSuccess[1]) {
      System.out.println("1111位置找到了!！！！！！！！");
      return true;
    }

    return false;
  }

  public static void enterKeyboard(boolean[] isSuccess, int[] positions, Map<String, Integer> skillContainers, int[] skill_release_distance, int[] startPosition) throws Exception {

    int[] keys = {skillContainers.get("xKey"), skillContainers.get("yKey")};
    int xAbs = Math.abs(positions[0] - (positions[2] + skill_release_distance[0] - X_POSITION_THRESHOLD));
    int yAbs = Math.abs(positions[1] - positions[3]);

    // 判定是否满足技能释放方位
    if ((skill_release_distance[0] >= 0 && positions[0] >= positions[2] + skill_release_distance[0] - (X_POSITION_THRESHOLD / 2))
            || (skill_release_distance[0] < 0 && positions[0] < positions[2] + skill_release_distance[0] - (X_POSITION_THRESHOLD / 2))

            && (xAbs <= X_POSITION_THRESHOLD * 1.5
            || positions[2] >= startPosition[0] + 800 - skill_release_distance[0] - X_POSITION_THRESHOLD)) {
      isSuccess[0] = true;
      skillContainers.put("xStatus", RELEASED);
    } else if (xAbs > 150) {
      TimeUnit.MILLISECONDS.sleep(60);
      MouseAndKeyEventUtil.doubleClick(keys[0]);
      skillContainers.put("xStatus", PRESS);
      isSuccess[0] = false;
      System.out.println("double keys[0]");
    } else {
      TimeUnit.MILLISECONDS.sleep(60);
      MouseAndKeyEventUtil.keyPress(keys[0]);
      skillContainers.put("xStatus", PRESS);
      isSuccess[0] = false;
      System.out.println("click keys[0]");
    }
    skillContainers.put("xKey", keys[0]);

    if (yAbs < POSITION_THRESHOLD) {
      isSuccess[1] = true;
      skillContainers.put("yStatus", RELEASED);
    } else {
      TimeUnit.MILLISECONDS.sleep(60);
      MouseAndKeyEventUtil.keyPress(keys[1]);
      skillContainers.put("yStatus", PRESS);
      isSuccess[1] = false;
      System.out.println("click keys[1]");
    }
    skillContainers.put("yKey", keys[1]);
  }
}
